///////////////////////////////////////////////////
// Textures & Samplers
///////////////////////////////////////////////////

texture MeshTexture;

sampler MeshSampler = sampler_state
{
	texture = <MeshTexture>; 
	magfilter = LINEAR;
	minfilter = LINEAR;
	mipfilter = LINEAR;
	AddressU = wrap;
	AddressV = wrap;
};

///////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////

float4x4 matrixViewProj;
float3 topColor;
float3 midTopColor;
float3 midLowColor;
float3 lowColor;
float3 CameraPosition;
static const float PI = 3.14159265f;
float4 fogColor = float4(0.6f, 0.6f, 0.6f, 1.0f); 
float fogStart = 500.0f;
float fogEnd = 530.0f;
float3 SunDirection = float3(-1, -1, -1);


///////////////////////////////////////////////////
// Helper functions
///////////////////////////////////////////////////

float4 ApplySunLight(float4 base, float3 normal)
{
	float light = dot(normal, -normalize(SunDirection));
	if(light < 0)
		light = 0;
	if(light > 0.5f)
		light = 0.5f + (light - 0.5f) * 0.65f;
		
	base.rgb *= light + 0.5f;
	return base;
}

float4 ApplyFog(float4 colorIn, float depth)
{
	if(depth < fogStart)
		return colorIn;

	float4 skyCol = colorIn;
	if(depth > fogEnd)
		return skyCol;

	float ratio = (depth - fogStart) / (fogEnd - fogStart);
	float4 col = float4(lerp(colorIn.rgb, skyCol.rgb, ratio), colorIn.a);
	return col;
}

float CalcDepth(float3 vertexPos)
{
	float dx = CameraPosition.x - vertexPos.x;
	float dy = CameraPosition.y - vertexPos.y;
	float dz = CameraPosition.z - vertexPos.z;
	return sqrt(dx * dx + dy * dy + dz * dz);
}



///////////////////////////////////////////////////
// Shader structs (PixelInput and VertexInput)
///////////////////////////////////////////////////

struct PixelInput
{
	float4 Position : POSITION0;
	float3 Normal : NORMAL;
	float2 TextureCoords : TEXCOORD0;
	float Depth : TEXCOORD1;
};

struct VertexInput
{
	float4 Position : POSITION0;
	float3 Normal : NORMAL;

	float2 TextureCoords : TEXCOORD0;
	float4 mat0 : TEXCOORD1;
	float4 mat1 : TEXCOORD2;
	float4 mat2 : TEXCOORD3;
	float4 mat3 : TEXCOORD4;
};



///////////////////////////////////////////////////
// Vertex-Shader
///////////////////////////////////////////////////

PixelInput MeshShader(VertexInput input)
{
	PixelInput retVal = (PixelInput)0;

	float4x4 modelMatrix = 
	{
		input.mat0,
		input.mat1,
		input.mat2,
		input.mat3
	};

	float4 instancePos = mul(input.Position, modelMatrix);

	retVal.Position = mul(instancePos, matrixViewProj);
	retVal.TextureCoords = input.TextureCoords;
	retVal.Depth = CalcDepth(instancePos.xyz);
	modelMatrix[3][0] = modelMatrix[3][1] = modelMatrix[3][2] = 0;
	modelMatrix[3][3] = 1;
	//float3 norm = mul(float4(input.Normal, 0.0f), modelMatrix).xyz;
	retVal.Normal = normalize(input.Normal);

	return retVal;
}



///////////////////////////////////////////////////
// Pixel-Shader
///////////////////////////////////////////////////

float4 PixelBlendShader(PixelInput input) : COLOR0
{
	float4 BaseColor = tex2D(MeshSampler, input.TextureCoords);

	BaseColor = ApplySunLight(BaseColor, input.Normal);
	return ApplyFog(BaseColor, input.Depth);
}

///////////////////////////////////////////////////
// Technique
///////////////////////////////////////////////////


technique Blend1Layer
{
	pass Pass1
	{
		VertexShader = compile vs_3_0 MeshShader();
		PixelShader = compile ps_3_0 PixelBlendShader();
	}
}